Django orm跨多值关联,链式调用filter/exclude数据与预期不符合问题

您所在的位置:网站首页 django filter 不等于 Django orm跨多值关联,链式调用filter/exclude数据与预期不符合问题

Django orm跨多值关联,链式调用filter/exclude数据与预期不符合问题

2023-08-25 18:41| 来源: 网络整理| 查看: 265

跨多值关联

当基于 ManyToManyField 或反向 ForeignKey 筛选某对象时,设 Blog/Entry 关联关系(Blog 对 Entry 是一种一对多关联关系)

Django 有一套统一的方式处理 filter() 调用。配置给某次 filter() 的所有条件会在调用时同时生效。

以下例子使用的models,如果需要验证的

from django.db import models class Blog(models.Model): name = models.CharField(max_length=32, null=False, blank=False) class Entry(models.Model): headline = models.CharField(max_length=32, null=False, blank=False) pub_date = models.DateField(null=True, blank=True) blog = models.ForeignKey(Blog, related_name="entry", on_delete=models.CASCADE) Filter

一. 对于多值关联来说,限制条件作用于链接至主模型的对象,而不一定是那些被前置 filter() 调用筛选的对象

例如:

Blog.objects.filter(entry__headline__contains='Lennon').filter(entry__pub_date__year=2008)

两段链式调用,都是作用域Blog模型,

第一个过滤器限制结果集为那些关联了标题包含 "Lennon" 的条目的博客。

第二个过滤器进一步要求结果集中的博客要发布于 2008 年。

第二个过滤器筛选的条目与第一个过滤器筛选的可能不尽相同。我们是用过滤器语句筛选 Blog,而不是 Entry

所以这条orm将筛选出包含 标题为"Lennon" 的博客和条目发布于 2008 年的博客(并不是同时包含标题为Lennon 的博客和发布于 2008 年)

举个例子:

Blog.objects.filter(entry__headline__contains='Lennon').filter(entry__pub_date__year=2008)

1,Blog和Entry是一对多关系,需要查询blog下 entry的headline包含lennon和pub_data__year=2008

2, Entry 这条数据包含lennon  ,Entry 这条数据 pub_data__year=2008,它们都是关联 Blog

3,所有 结果是``

4, 结论 这条orm将筛选出包含 标题为"Lennon" 的博客和条目发布于 2008 年的博客(并不是同时包含标题为Lennon 的博客和发布于 2008 年)

二.那么要实现标题含有 标题为"Lennon" 且发布于 2008 (同一个条目,同时满足两个条件)年的博客

例如:

Blog.objects.filter(entry__headline__contains='Lennon', entry__pub_date__year=2008) Blog.objects.filter(entry__headline__contains='Lennon',entry__pub_date__year=2008)

Exclude

一. filter() 的查询行为会跨越多值关联,就像前文说的那样,但 exclude() 不是这样。

例如:

Blog.objects.exclude( entry__headline__contains='Lennon', entry__pub_date__year=2008, )

查询出排除那些关联条目标题包含 "Lennon" 和同时满足有发布于 2008 年的博客

(只要多条数据中一条满足一个过滤条件即可,但必须是要有两种满足)

但并不会限制博客同时满足这两种条件NOT(id in A ∩ id in B)

举个例子:

数据同上

Blog.objects.exclude( entry__headline__contains='Lennon', entry__pub_date__year=2008, )

1. 这个语句并不是排除同时满足这两种条件的

2. 从结果看来,只查到这一条

3,Blog 是一条Entry满足entry__pub_date__year=2008,一条满足entry__headline__contains='Lennon'

二. 那么要满足 多条数据中一条满足一个过滤条件即可,但不必须是要有两种满足,实现如下:NOT id in A and NOT id in B

Blog.objects.exclude( entry__pub_date__year=2008, ).exclude(entry__headline__contains='Lennon')

3. 那么要满足同时两种条件(在同一条目满足两个条件)实现如下:NOT (id in (A and B))

Blog.objects.exclude( entry__in=Entry.objects.filter( headline__contains='Lennon', pub_date__year=2008, ), )



【本文地址】


今日新闻


推荐新闻


    CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3